Skip to content

python-stdlib/enum/enum.py: Add Enum class.#980

Open
IhorNehrutsa wants to merge 14 commits into
micropython:masterfrom
IhorNehrutsa:enum
Open

python-stdlib/enum/enum.py: Add Enum class.#980
IhorNehrutsa wants to merge 14 commits into
micropython:masterfrom
IhorNehrutsa:enum

Conversation

@IhorNehrutsa

@IhorNehrutsa IhorNehrutsa commented Mar 5, 2025

Copy link
Copy Markdown

Docs in:
docs/library/enum.rst: Add Enum class. #16842
Usage example:

from enum import Enum

class Color(Enum):
    RED = 'red'
    GREEN = 'green'

# Initialize the enum to process attributes
c = Color()

print(c.RED)        # Output: RED: red
print(c.RED.name)   # Output: RED
print(c.RED.value)  # Output: red
print(c.RED())      # Output: red

EDITED:
Inspired by @shariltumin Dot class from the Way to use dot notation to refer to states in a state machine #15694
and @njourdane enum() func from the Request for package: micropython-enum #269

EDITED April 2026:
Gemini-based version of enum.py and unit test test_enum.py

Code size report:

esp32: +1968 +0.113% ESP32_GENERIC[incl +1968(data)]

@IhorNehrutsa

IhorNehrutsa commented Mar 5, 2025

Copy link
Copy Markdown
Author

Usage example::

from enum import Enum

class State(Enum):
  Stop = 10
  Run = 20
  Ready = 30

state = State()
print("state:", State())

current_state = state.Stop
print("current_state:", current_state, current_state.name)
if current_state == state.Stop:
  print(" Stop state")
if current_state != state.Ready:
  print(" Not a Ready state")
  print(" Run!")
  current_state = state.Run
print("current_state:", current_state, current_state.name)
# some process
i = -1
while current_state != state.Ready:
  i += 1
  if state.is_value(i):
      if state(i) == state.Ready:
          current_state = state.Ready
  print(".", end="")
print()
print("current_state:", current_state, state(current_state))
print("Done!")

Output is::

state: State(names={'Run': 20, 'Stop': 10, 'Ready': 30})
current_state: Stop: 10 Stop
 Stop state
 Not a Ready state
 Run!
current_state: Run: 20 Run
...............................
current_state: Ready: 30 Ready: 30
Done!

@dpgeorge

Copy link
Copy Markdown
Member

Thanks for the contribution, this looks pretty good!

Did you implement this from scratch, or copy parts from CPython's implementation? I'm just wondering about licensing and copyright.

Can you please add the test to the CI, in tools/ci.sh inside the function ci_package_tests_run.

@IhorNehrutsa

Copy link
Copy Markdown
Author

Did you implement this from scratch, or copy parts from CPython's implementation?

I just saw CPython Enum. It looks like incredible magic. :-)

@dpgeorge

Copy link
Copy Markdown
Member

I just saw CPython Enum. It looks like incredible magic. :-)

That doesn't really answer the question. Did you copy this implementation from CPython?

Also, please make sure the CI all passes, there's currently a failure.

@IhorNehrutsa

Copy link
Copy Markdown
Author

| Did you implement this from scratch, or copy parts from CPython's implementation?

No, I didn't use CPython implementation.

It was inspired by @shariltumin Dot class from the Way to use dot notation to refer to states in a state machine #15694
and @njourdane enum() func from the Request for package: micropython-enum #269

Comment thread python-stdlib/enum/manifest.py Outdated
@IhorNehrutsa IhorNehrutsa force-pushed the enum branch 2 times, most recently from e70dd06 to 6ab2ebe Compare March 12, 2025 07:34
@IhorNehrutsa

Copy link
Copy Markdown
Author

Should I squash commits?

Comment thread python-stdlib/enum/test_enum.py Outdated
@@ -0,0 +1,91 @@
# enum_test.py

from enum import Enum, enum

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to run this test under CPython 3.12.2 but it doesn't work, for many reasons. And it should run under CPython so we can test that the implementation of MicroPython's enum matches the CPython enum.

For example, enum does not exist in the enum CPython module. Which version of CPython were you testing against?

Comment thread python-stdlib/enum/test_enum.py Outdated
Enabled = True


state = Enum()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CPython cannot create enums in this way.

Comment thread python-stdlib/enum/test_enum.py Outdated

state = Enum()
print(state)
state = Direction()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CPython requires a value in the constructor here.

Comment thread python-stdlib/enum/test_enum.py Outdated
print(state)
state = State()
print(state)
state = State({"X": 1.0, "Y": 2.0})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CPython doesn't allow such an argument to the constructor.

Comment thread python-stdlib/enum/test_enum.py Outdated

print("Direction(Direction.CCW):", Direction(Direction.CCW))
print("Direction('CW'):", Direction("CW"))
print("state(10):", state(10))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CPython doesn't allow calling an enum.

Comment thread python-stdlib/enum/test_enum.py Outdated
print("state('CW'):", state("CW"))
print("type(state('CW')):", type(state("CW")))

print("state.key_from_value(20):", state.key_from_value(20))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CPython doesn't have key_from_value().

Comment thread python-stdlib/enum/test_enum.py Outdated
CCW = "CCW"


class State(Direction):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CPython doesn't allow inheriting enums from each other.

Comment thread python-stdlib/enum/test_enum.py Outdated
print("type(state('CW')):", type(state("CW")))

print("state.key_from_value(20):", state.key_from_value(20))
print("len(state):", len(state))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CPython doesn't have __len__ on an enum.

Comment thread python-stdlib/enum/test_enum.py Outdated

print("state.keys():", state.keys())
print("state.values():", state.values())
print("state.items():", state.items())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CPython enums don't have keys/values/items methods.

@jonnor

jonnor commented Apr 25, 2025

Copy link
Copy Markdown

There is a quite comprehensive set of unit-tests for enum available in CPython: https://github.com/python/cpython/blob/main/Lib/test/test_enum.py
With some exceptions like the tests using inspect, threading, pickle it seems possible to port most of them to MicroPython. That would give a very high degree of confidence that the implementation is conformant. And in the cases that one chooses to not be conformant, that can be documented with skipped tests.

@IhorNehrutsa

Copy link
Copy Markdown
Author

I have successfully completed the task that requires the Enum class.
I don't plan to support this PR in the future.
You are welcome to continue working with this PR as you wish.
Thanks everyone.

rtyley added a commit to rtyley/analogue-led-clock that referenced this pull request Mar 22, 2026
We need to mip install `datetime`, tzif-parser requires it.

https://github.com/micropython/micropython-lib/tree/master/python-stdlib/datetime

```
mpremote connect id:a5f14b8bfbff4289 mip install datetime
```

## CPython features originally used in `tzif-parser` which were missing or different in MicroPython

* `sysconfig`
* `enum`
  - micropython/micropython-lib#269
  - micropython/micropython-lib#980
* Regex _named_ Groups
  - https://docs.python.org/3/howto/regex.html#non-capturing-and-named-groups
  - https://docs.micropython.org/en/latest/library/re.html
* `dataclasses`
  - https://docs.python.org/3/library/dataclasses.html
  - https://github.com/orgs/micropython/discussions/13741
  - https://github.com/dhrosa/udataclasses - https://udataclasses.readthedocs.io/en/latest/
* `struct` (https://docs.python.org/3/library/struct.html#format-characters) features not
  available in MicroPython (https://docs.micropython.org/en/latest/library/struct.html#module-struct):
  - `c` for `char`, which in CPython would be decoded as an instance of [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes-objects) with length 1. Instead of `c`, we could use `s`, but we know this is a single byte, so `b` does just fine, giving us a Python integer. The integral repeat count prefix `1` is superfluous.
* [MicroPython `bytearray`](https://www.fredscave.com/43-micropython-data-types-bytearray.html) type doesn't have the [`clear()`](https://docs.python.org/3/library/stdtypes.html#sequence.clear) method [mutable sequences](https://docs.python.org/3/library/stdtypes.html#typesseq-mutable) in CPython do
* `Typing.IO`
  - python/typing#829
rtyley added a commit to rtyley/analogue-led-clock that referenced this pull request Mar 22, 2026
We need to mip install `datetime`, tzif-parser requires it.

https://github.com/micropython/micropython-lib/tree/master/python-stdlib/datetime

```
mpremote connect id:a5f14b8bfbff4289 mip install datetime
```

## CPython features originally used in `tzif-parser` which were missing or different in MicroPython

* `sysconfig`
* `enum`
  - micropython/micropython-lib#269
  - micropython/micropython-lib#980
* Regex _named_ Groups
  - https://docs.python.org/3/howto/regex.html#non-capturing-and-named-groups
  - https://docs.micropython.org/en/latest/library/re.html
* `dataclasses`
  - https://docs.python.org/3/library/dataclasses.html
  - https://github.com/orgs/micropython/discussions/13741
  - https://github.com/dhrosa/udataclasses - https://udataclasses.readthedocs.io/en/latest/
* `struct` (https://docs.python.org/3/library/struct.html#format-characters) features not
  available in MicroPython (https://docs.micropython.org/en/latest/library/struct.html#module-struct):
  - `c` for `char`, which in CPython would be decoded as an instance of [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes-objects) with length 1. Instead of `c`, we could use `s`, but we know this is a single byte, so `b` does just fine, giving us a Python integer. The integral repeat count prefix `1` is superfluous.
* [MicroPython `bytearray`](https://www.fredscave.com/43-micropython-data-types-bytearray.html) type doesn't have the [`clear()`](https://docs.python.org/3/library/stdtypes.html#sequence.clear) method [mutable sequences](https://docs.python.org/3/library/stdtypes.html#typesseq-mutable) in CPython do
* `Typing.IO`
  - python/typing#829
@mchobby

mchobby commented Apr 11, 2026

Copy link
Copy Markdown

@dpgeorge
This PR looks stuck in time. I didn't find enum.py in micropython-lib/python-stdlib/enum.py .
Getting Enum for MicroPython would be really useful .

Need some help on this PR ? Were could I start ?

Dominique

@Josverl

Josverl commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Need some help on this PR ? Were could I start ?

That would be much appreciated.
I would suggest that making it match Cpython more and changing/adding tests to prove that would be the next step

@IhorNehrutsa

Copy link
Copy Markdown
Author

@mchobby @Josverl You may pull down this PR and try to use enum.py. Please write reviews about usage here

@Josverl

Josverl commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

@IhorNehrutsa, may I ask why you closed the documentation PR?

@IhorNehrutsa

Copy link
Copy Markdown
Author

@IhorNehrutsa, may I ask why you closed the documentation PR?

This has been going on for so long that I forgot. :(

@mchobby

mchobby commented Apr 15, 2026

Copy link
Copy Markdown

I'm a bit skeptical about the last @IhorNehrutsa action.
As I understand, the initial PR enum.py behavior was too far from CPython implementation.
I was interested to help in reducing the gap between CPython & MicroPython implementation.
That was looking as a "Good-First-Issue" to me (and for me).

On the meanwhile, @IhorNehrutsa pushed an AI rework of the code and "here is it for you to test".
As last arrival in this PR (and micropython-lib), I'm not in great position to evaluate the appropriateness of that rework.
@Josverl could you have a quick review on this for guidance?

Nevertheless, I do not want to be retrograde but being the "human behind the IA for checking the IA work" is not really what I was expecting.
Cheers

@Josverl

Josverl commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

@mchobby,
I agree with the earlier comments that it isn’t the reviewer’s job to try to interpret or “fix up” clearly AI‑generated submissions. If the submitter isn’t putting in at least the same level of effort as the reviewers, the process becomes unbalanced and unsustainable.
That does not mean that AI is not to be used as a tool to create code, but it does mean that there needs to be more that just that.

@IhorNehrutsa , I’m also genuinely confused by the pattern of behavior around these PRs: starting work, abandoning it, then suddenly re‑engaging with AI‑generated updates, along with the closing, and re‑opening of related PRs. It makes it difficult to understand the actual intent, the direction of the contribution, or whether you are committed to following through.
to be clear - I do appreciate your efforts, and I realize that sometimes the wait for a PR to get merged (or even rejected) can exceed ones attention span. but in order for us to work as a community I prefer to have some level confidence.

There is clear interest in having an Enum class available in MicroPython. But implementing one properly is non‑trivial — it touches (the lack of) metaclasses, memory constraints, and the broader philosophy of keeping the core minimal.

At the same time, it’s important that MicroPython stays close to CPython where feasible, while still respecting MicroPython’s own design principles and constraints. Achieving that balance requires careful design and discussion, not a surface‑level or (mostly) AI‑generated port.

I have not had the time to look at the most recent tests and code - but I do plan to do that in the next few days.

@IhorNehrutsa

Copy link
Copy Markdown
Author

Okay. No one minds if I copy the previous version of enum.py to enum_0.py, the latest to enum_1.py, then we'll choose the best implementation options for enum.py from them.

@IhorNehrutsa

Copy link
Copy Markdown
Author

There is a quite comprehensive set of unit-tests for enum available in CPython: https://github.com/python/cpython/blob/main/Lib/test/test_enum.py With some exceptions like the tests using inspect, threading, pickle it seems possible to port most of them to MicroPython. That would give a very high degree of confidence that the implementation is conformant. And in the cases that one chooses to not be conformant, that can be documented with skipped tests.

Can someone write a MicroPython version of the CPython tests https://github.com/python/cpython/blob/main/Lib/test/test_enum.py ?

Add Enum class.
tools\ci.sh: Add test_enum.py to the CI.

Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
Gemini was used

Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
    class Status(Enum):
        IDLE = 0
        RUNNING = 1
        ERROR = 2

    # This simulates receiving a byte from the  hardware
    received_byte = 1
    status = Status(received_byte)
    print(f"Lookup check: Received {received_byte} -> {status}")
    assert status == Status.RUNNING
    assert status.name == "RUNNING"

Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
igned-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
@IhorNehrutsa

Copy link
Copy Markdown
Author

Code size report:
esp32: +1968 +0.113% ESP32_GENERIC[incl +1968(data)]

Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
@IhorNehrutsa

Copy link
Copy Markdown
Author

Code size report:
esp32: +1712 +0.098% ESP32_GENERIC[incl +1712(data)]

Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
@IhorNehrutsa

Copy link
Copy Markdown
Author

Code size report:
esp32: +2688 +0.154% ESP32_GENERIC[incl +2688(data)]

@Josverl

Josverl commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

@IhorNehrutsa
I suggest to change the status of these PRs to Draft.
You appear to still be working through both the functionality offered as well as the code size -
You keep making regular updates - which is fine - setting the draft / would help let maintainers know when it is stable enough to spend more time reviewing it.

@IhorNehrutsa

Copy link
Copy Markdown
Author

Code size report:
esp32: +1568 +0.090% ESP32_GENERIC[incl +1568(data)]

@IhorNehrutsa

Copy link
Copy Markdown
Author

I think I've reached the maximum functionality and minimum code size. Right now, I'm missing feedback.

@IhorNehrutsa IhorNehrutsa force-pushed the enum branch 3 times, most recently from 018909b to e5dae28 Compare April 29, 2026 13:19
@IhorNehrutsa IhorNehrutsa requested a review from dpgeorge April 29, 2026 13:21
Signed-off-by: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
@IhorNehrutsa

Copy link
Copy Markdown
Author

Code size report:
esp32: +1600 +0.092% ESP32_GENERIC[incl +1600(data)]
mimxrt: +1568 +0.407% TEENSY40
rp2: +1564 +0.170% RPI_PICO_W
samd: +1564 +0.569% ADAFRUIT_ITSYBITSY_M4_EXPRESS

@IhorNehrutsa

Copy link
Copy Markdown
Author

Ready for review

@IhorNehrutsa

Copy link
Copy Markdown
Author

Is there any feedback?

@Josverl

Josverl commented May 27, 2026

Copy link
Copy Markdown
Contributor

One of the twenty-something post its on my MicroPython to-do list is to do a full review and comparison.

But I can't give you a date

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants